package com.cgc.venus.server.filter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.cgc.venus.server.utils.ApiRouteConfig;
import com.cgc.venus.server.utils.HttpClientUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;


/**
 * Created by xyr on 2017/9/4.
 * 在路由前进行拦截
 * 1: 拦截token,进行请求验证
 */
public class LoginFilter extends ZuulFilter {

    // 项目配置文件类
    @Autowired
    private ApiRouteConfig apiRouteConfig;


    @Override
    public Object run() {
        // 此处为逻辑方法
        RequestContext ctx = RequestContext.getCurrentContext();

        HttpServletRequest request = ctx.getRequest();

        // 获得请求URL
        String req_url = request.getRequestURI().toString();

        // 获得请求头的token
        String req_token = request.getHeader(apiRouteConfig.getTokenKey());
        if (StringUtils.isBlank(req_token))
            req_token = request.getHeader("x-token");


        boolean sendZuulResponse = true;
        int responseStatusCode = 200;
        String responseBody = "";

        // 1:如果请求URL是登录接口,且req_token为null,则通过
        // 2:如果请求URL不是登录接口,且req_token不为为null,登录只允许单点登录,所以判断客户端token和数据库登记的token是否一致,并且登录session是否失效
        // 3:如果请求URL不是登录接口,且且req_token为null

        if (StringUtils.isNotBlank(req_token) && req_url.indexOf(apiRouteConfig.getLoginUrl()) == -1) {
            // 如果请求URL不是登录接口,且req_token不为为null,
            // 登录只允许单点登录,所以判断客户端token和数据库登记的token是否一致,
            // 并且登录session是否失效
            String getUrl = apiRouteConfig.getValidateTokenUrl()+"/"+req_token;
            String result  = HttpClientUtils.doGet(getUrl,apiRouteConfig.getRequestTimeOut());
            if (result.indexOf("{\"code\":200") == -1){
                // 返回的code不是200,不通过
                sendZuulResponse = false;
                responseBody = result;
            }
        } else if (req_url.indexOf(apiRouteConfig.getLoginUrl()) != -1 || req_url.indexOf(apiRouteConfig.getValidateAccountUrl()) != -1
                    || req_url.indexOf(apiRouteConfig.getValidatePasswordUrl()) != -1
                    || req_url.indexOf(apiRouteConfig.getValidateHealthUrl()) != -1){
            // 如果请求URL是登录接口,放心通过
            // 验证登录账号接口,放心通过
            // 验证密码接口,放心通过
            sendZuulResponse = true;
        } else {
            // 非法请求
            sendZuulResponse = false;
            responseBody = "{\"meta\":{\"code\":444,\"message\":\"Illegal Request\"},\"data\":{\"token\":\""+req_token+"\"}}";
        }

        // 处理错误返回,重新定义返回HttpServletResponse,此步骤关键,解决跨域问题
        if (!sendZuulResponse) {
            HttpServletResponse response = ctx.getResponse();
            response.setHeader("Access-Control-Allow-Origin","*");
            response.setHeader("Access-Control-Allow-Credentials","true");
            response.setHeader("Content-Type","application/json;charset=UTF-8");
            response.setHeader("Access-Control-Allow-Headers", "X-Token,operObjectName,Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
            response.setHeader("Access-Control-Allow-Methods", "DELETE,GET,PUT,POST,PATCH");
            response.setStatus(200);
            ctx.setResponse(response);
        }

        // 返回客户端
        ctx.setSendZuulResponse(sendZuulResponse);
        ctx.setResponseStatusCode(responseStatusCode);
        if (StringUtils.isNotBlank(responseBody)) {
            ctx.setResponseBody(responseBody);
        }
        return null;
    }

    /*
    * filterType：返回一个字符串代表过滤器的类型，在zuul中定义了四种不同生命周期的过滤器类型，具体如下：
    *   pre：可以在请求被路由之前调用
    *   route：在路由请求时候被调用
    *   post：在route和error过滤器之后被调用
    *   error：处理请求时发生错误时被调用
    * */
    @Override
    public String filterType() {
        // 前置过滤器
        return "pre";
    }

    @Override
    public int filterOrder() {
        // 优先级为0，数字越大，优先级越低
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        // 是否执行该过滤器，此处为true，说明需要过滤
        return true;
    }


}
